﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Mvc;

namespace SpeadFrm.Web.Mvc
{
    public class JQueryHelper
    {
        public static Validate Validate(string name)
        {
            return new Validate(name);
        }
    }

    public static class ValidateExtension
    {
        public static MvcHtmlString ToMvcHtmlString(this Validate validate)
        {
            return MvcHtmlString.Create(validate.ToString());
        }
    }

    public class Validate
    {
        private string mName;

        public Validate(string id)
        {
            mName = id;

        }

        private List<ValidateItem> mItems = new List<ValidateItem>(8);

        public Validate Add(string name, Action<ValidateItem> addaction)
        {
            ValidateItem item = new ValidateItem(name);
            mItems.Add(item);
            addaction(item);
            return this;
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            ValidateItem item;
            sb.Append("<script type=\"text/javascript\">\r\n");
            sb.Append("$(function() {");
            sb.Append(" $('#").Append(mName).Append("').validate({\r\n");
            sb.Append("  rules: {\r\n");
            for (int i = 0; i < mItems.Count; i++)
            {
                item = mItems[i];
                if (i > 0)
                    sb.Append(",");
                sb.Append(item.Name).Append(":{");
                for (int k = 0; k < item.Items.Count; k++)
                {
                    if (k > 0)
                        sb.Append(",");
                    sb.Append(item.Items[k].Name).Append(":").Append(item.Items[k].Value);
                }
                sb.Append("}");
            }
            sb.Append("},\r\n messages: {\r\n");

            for (int i = 0; i < mItems.Count; i++)
            {
                item = mItems[i];
                if (i > 0)
                    sb.Append(",");
                sb.Append(item.Name).Append(":{");
                if (item.HasMessage)
                {
                    int count = 0;
                    for (int k = 0; k < item.Items.Count; k++)
                    {
                        if (count > 0)
                            sb.Append(",");
                        if (!string.IsNullOrEmpty(item.Items[k].Message))
                        {
                            sb.Append(item.Items[k].Name).Append(":'").Append(item.Items[k].Message).Append("'");
                            count++;
                        }
                    }
                }
                sb.Append("}");
            }
            sb.Append(" }\r\n"); 
            sb.Append("});\r\n");
            sb.Append("});");
            sb.Append("</script>\r\n");
            return sb.ToString();
        }
    }

    public class ValidateItem
    {


        public ValidateItem(string name)
        {
            Name = name;
            HasMessage = false;
        }

        public string Name { get; set; }

        public ValidateItem required()
        {
            return AddType("required", "true", null);
        }

        public ValidateItem required(string message)
        {
            return AddType("required", "true", message);
        }
        public ValidateItem required(string value, string message)
        {
            return AddType("required", "'" + value + "'", message);
        }
        public ValidateItem remote(string url)
        {
            return AddType("remote", url, null);
        }

        public ValidateItem remote(string url, string message)
        {
            return AddType("remote", url, message);
        }

        public ValidateItem remote(string url, string dataexpression, string message)
        {
            return AddType("remote", "{url:'" + url + "',type:'POST',data:" + dataexpression + "}", message);
        }

        public ValidateItem email()
        {
            return AddType("email", "true", null);
        }

        public ValidateItem email(string message)
        {
            return AddType("email", "true", message);
        }

        public ValidateItem url()
        {
            return AddType("url", "true", null);
        }

        public ValidateItem url(string message)
        {
            return AddType("url", "true", message);
        }

        public ValidateItem date()
        {
            return AddType("date", "true", null);
        }

        public ValidateItem date(string message)
        {
            return AddType("date", "true", message);
        }

        public ValidateItem dateISO()
        {
            return AddType("dateISO", "true", null);
        }

        public ValidateItem dateISO(string message)
        {
            return AddType("dateISO", "true", message);
        }

        public ValidateItem number()
        {
            return AddType("number", "true", null);
        }

        public ValidateItem number(string message)
        {
            return AddType("number", "true", message);
        }

        public ValidateItem digits()
        {
            return AddType("digits", "true", null);
        }

        public ValidateItem digits(string message)
        {
            return AddType("digits", "true", message);
        }

        public ValidateItem creditcard()
        {
            return AddType("creditcard", "true", null);
        }

        public ValidateItem creditcard(string message)
        {
            return AddType("creditcard", "true", message);
        }

        public ValidateItem equalTo(string control)
        {
            return AddType("equalTo", "'#" + control + "'", null);
        }

        public ValidateItem equalTo(string control, string message)
        {
            return AddType("equalTo", "'#" + control + "'", message);
        }

        /// <summary>
        /// $("#myform").validate({
        ///     rules: {
        ///         field: {
        ///             required: true,
        ///             accept: "xls|csv"
        ///         }
        ///      }
        ///});
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public ValidateItem accept(string type)
        {
            return AddType("accept", type, null);
        }

        /// <summary>
        /// $("#myform").validate({
        ///     rules: {
        ///         field: {
        ///             required: true,
        ///             accept: "xls|csv"
        ///         }
        ///      }
        ///});
        /// </summary>
        /// <param name="type"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public ValidateItem accept(string type, string message)
        {
            return AddType("accept", type, message);
        }

        public ValidateItem maxlength(int length)
        {
            return AddType("maxlength", length, null);
        }

        public ValidateItem maxlength(int length, string message)
        {
            return AddType("maxlength", length, message);
        }

        public ValidateItem minlength(int length)
        {
            return AddType("minlength", length, null);
        }

        public ValidateItem minlength(int length, string message)
        {
            return AddType("minlength", length, message);
        }

        public ValidateItem rangelength(int min, int max)
        {
            return AddType("rangelength", string.Format("[{0},{1}]", min, max), null);
        }

        public ValidateItem minlength(int min, int max, string message)
        {
            return AddType("rangelength", string.Format("[{0},{1}]", min, max), message);
        }

        public ValidateItem range(object min, object max)
        {
            return AddType("range", string.Format("[{0},{1}]", min, max), null);
        }

        public ValidateItem range(object min, object max, string message)
        {
            return AddType("range", string.Format("[{0},{1}]", min, max), message);
        }

        public ValidateItem max(object value)
        {
            return AddType("max", value, null);
        }

        public ValidateItem max(object value, string message)
        {
            return AddType("max", value, message);
        }

        public ValidateItem min(object value)
        {
            return AddType("min", value, null);
        }

        public ValidateItem min(object value, string message)
        {
            return AddType("min", value, message);
        }

        public ValidateItem AddType(ValidateType type, object value)
        {
            return AddType(Enum.GetName(typeof(ValidateType), type), value, null);
        }

        public ValidateItem AddType(ValidateType type, object value, string message)
        {
            return AddType(Enum.GetName(typeof(ValidateType), type), value, message);
        }

        public bool HasMessage
        {
            get;
            set;
        }

        public ValidateItem AddType(string type, object value, string message)
        {
            ValidateSubItem item = new ValidateSubItem { Name = type, Message = message, Value = value };
            if (!string.IsNullOrEmpty(item.Message))
                HasMessage = true;
            Items.Add(item);
            return this;
        }

        private IList<ValidateSubItem> mItems = new List<ValidateSubItem>();

        public IList<ValidateSubItem> Items
        {
            get
            {
                return mItems;
            }
        }

        public class ValidateSubItem
        {
            public string Name;
            public object Value;
            public string Message;
        }
    }

    public enum ValidateType
    {
        required,
        remote,
        email,
        url,
        date,
        dateISO,
        number,
        digits,
        creditcard,
        equalTo,
        accept,
        maxlength,
        minlength,
        rangelength,
        range,
        max,
        min
    }

}